package com.nforce.linremote.networking;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import com.google.gson.Gson;
import com.nforce.linremote.model.Packet;

public class LRSocket {

    private final static int SOCKET_TIMEOUT = 1500;
    private final static int INITIAL_BUFFER_SIZE = 60;

    private DatagramSocket socket;
    private DatagramPacket packet;
    private final String remoteIp;
    private final int remotePort;

    public LRSocket(String ip, int port) {
	try {
	    socket = new DatagramSocket();
	} catch (SocketException e) {
	    handleException(e);
	}
	remoteIp = ip;
	remotePort = port;
    }

    public boolean send(byte[] bCommand) {
	InetAddress remoteAddress;

	try {
	    remoteAddress = InetAddress.getByName(remoteIp);
	    packet = new DatagramPacket(bCommand, bCommand.length,
		    remoteAddress, remotePort);
	} catch (UnknownHostException e) {
	    handleException(e);
	    return false;
	}

	if (packet == null) {
	    return false;
	}

	try {
	    socket.send(packet);
	} catch (IOException e) {
	    handleException(e);
	    return false;
	}

	return true;
    }

    public Packet recieve(byte[] command) {
	if (send(command)) {
	    Packet result = recieve();
	    close();
	    return result;
	}
	return null;
    }

    private Packet recieve() {
	Packet p = new Packet();

	byte bData[] = new byte[INITIAL_BUFFER_SIZE];
	packet = new DatagramPacket(bData, bData.length);
	try {
	    socket.setSoTimeout(SOCKET_TIMEOUT);
	} catch (SocketException e) {
	    handleException(e);
	    return null;
	}
	try {
	    socket.receive(packet);
	    String bufferJson = new String(bData, 0, packet.getLength());
	    BufferResponse br = new Gson().fromJson(bufferJson,
		    BufferResponse.class);
	    bData = new byte[br.buffer];
	    packet = new DatagramPacket(bData, bData.length);
	    socket.receive(packet);
	} catch (IOException e) {
	    handleException(e);
	    return null;
	}

	p.setIpAddress(packet.getAddress().getHostAddress());
	p.setPort(packet.getPort());
	p.setData(bData);

	return p;
    }

    private class BufferResponse {
	public int buffer;
    }

    private void close() {
	if (socket != null) {
	    socket.close();
	}
    }

    private void handleException(Exception e) {
	// Log.d(StartActivity.DEBUG_TAG, e.toString());
	close();
    }
}
